#include "xftp_list.h"

#include <iostream>
#include <event2/event.h>
#include <event2/bufferevent.h>

#ifdef _WIN32
#include <io.h>
#else

#endif

using namespace std;

XFtpList::XFtpList() {
}

XFtpList::~XFtpList() {
}

void XFtpList::Parse(std::string type, std::string msg) {
    std::string resmsg = "";
    if (type == "PWD") {
        // 257 "/" is current directory
        resmsg = "257 \"";
        resmsg += cmdTask->curDir;
        resmsg += "\" is current dir.\r\n";
        ResCmd(msg); 
    } else if (type == "LIST") {
        // 1.连接数据通道 2.150 3.发送目录数据通道 4.发送完成226 5.关闭连接
        // 命令通道回复消息 使用数据通道发送目录
        // 1.连接数据通道
        ConnectPort();
        // 2.150
        ResCmd("150 Here comes the directory listing.\r\n");
        // std::string listdata = "-rwxrwxrwx 1 root group 64463 Mar 14 09:53 101.jpg\r\n";
        
        std::string listdata = GetListData(cmdTask->rootDir + cmdTask->curDir);
        // 3.数据通道发送
        Send(listdata);
    } else if (type == "CWD") {
        // 取出命令中的路径
        // CWD test\r\n
        int pos = msg.rfind(" ") + 1;
        // 去掉结尾的\r\n
        string path = msg.substr(pos, msg.size() - pos - 2);
        if (path[0] == '/') { // 绝对路径
            cmdTask->curDir = path;
        } else {
            if (cmdTask->curDir[cmdTask->curDir.size() - 1] != '/') {
                cmdTask->curDir += "/";
            }
            cmdTask->curDir +=  path + "/";
        }

        ResCmd("250 Directory success changed.\r\n");
    } else if (type == "CDUP") { // 回到上层目录
        string path = cmdTask->curDir;
        // 统一去掉结尾的/
        if (path[path.size() - 1] == '/') {
            path = path.substr(0, path.size() - 1);
        }

        int pos = path.rfind("/");
        path = path.substr(0, pos);

        cmdTask->curDir = path;

        ResCmd("250 Directory success changed.\r\n");
    } 
}

void XFtpList::Write(struct bufferevent *bev) {
    // 4.发送完成226
    ResCmd("226 Transfer complete\r\n"); 
    // 5.关闭连接
    Close();
}

void XFtpList::Event(struct bufferevent *bev, short what) {
    // 如果对方网络断掉,或者机器死机有可能收不到BEV_EVENT_EOF数据
    if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
        cout << "BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT" << endl;
        Close();
    } else if (what & BEV_EVENT_CONNECTED) {
        cout << "XFtpList BEV_EVENT_CONNECTED" << endl; 
    }

}

std::string XFtpList::GetListData(std::string path) {
    // "-rwxrwxrwx 1 root group 64463 Mar 14 09:53 101.jpg\r\n";
    string data = "";
#ifdef _WIN32
    // 存储文件信息
    _finddata_t file;
    // 目录上下文
    path += "/*.*";
    inptr_t dir = _findfirst(path.c_str(), &file);
    if (dir < 0) {
        return data;
    }

    do {
        string tmp = "";
        // 是否是目录
        if (file.attrib & _A_SUBDIR) {
            if (strcmp(file.name, ".") == 0 || strcmp(file.name, "..") == 0) {
                continue;
            }

            tmp = "drwxrwxrwx 1 root group ";
        } else {
            tmp = "-rwxrwxrwx 1 root group ";
        }

        // 文件大小
        char buf[1024] = {0};
        sprintf(buf, "%u ", file.size);
        tmp += buf;

        // 日期
        memset(buf, 0, sizeof(buf));
        strftime(buf, sizeof(buf) - 1, "%b %d $H:%M ", localtime(&file.time_write));
        tmp += buf;

        tmp += file.name;

        data += tmp;
        data += "\r\n";

    } while(_findnext(dir, &file) == 0);
#else
    // data = "-rwxrwxrwx 1 root group 64463 Mar 14 09:53 101.jpg\r\n";
    string cmd = "ls -l ";
    cmd += path;
    FILE *f = popen(cmd.c_str(), "r");
    if (!f) {
        return data;
    }

	char buf[1024] = {0};
    for (;;) {
        int len = fread(buf, 1, sizeof(buf) - 1, fp);
        if (len <= 0) break;
		buf[len] = '\0';
		data += buf;

    }
	pclose(f);
#endif

    return data;
}

